package com.demo.demoproject.utils;

import com.demo.demoproject.constants.SecretKeysConstants;
import io.jsonwebtoken.security.Keys;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

@Component
@RequiredArgsConstructor
public class SecretKeysUtil {
    private final StringRedisTemplate stringRedisTemplate;
    private static final CustomString SECRET_KEY = new CustomString().addString("secret").addStringWithColon("key");

    /**
     * 加密数据
     *
     * @param data 要加密的明文数据
     * @return 加密后的数据，以Base64编码的字符串形式返回
     * @throws IllegalArgumentException 如果数据为空
     * @throws Exception              如果加密过程中发生异常
     */
    public static String encryptAES(@NotNull String data) throws Exception {
        if (data.isEmpty()) {
            throw new IllegalArgumentException("要加密的数据不能为空");
        }

        try {
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, SecretKeysConstants.SECRET_KEY_AES);
            byte[] encryptedBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(encryptedBytes);
        } catch (Exception e) {
            throw new RuntimeException("加密过程中出现错误", e);
        }
    }

    /**
     * 解密数据。
     *
     * @param encryptedData 要解密的Base64编码的字符串数据
     * @return 解密后的明文数据
     * @throws IllegalArgumentException 如果数据为空或格式不正确
     * @throws Exception              如果解密过程中发生异常
     */
    @NotNull
    @Contract("_ -> new")
    public static String decryptAES(@NotNull String encryptedData) throws Exception {
        if (encryptedData.isEmpty()) {
            throw new IllegalArgumentException("要解密的数据不能为空");
        }

        try {
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, SecretKeysConstants.SECRET_KEY_AES);
            byte[] decodedBytes = Base64.getDecoder().decode(encryptedData);
            byte[] decryptedBytes = cipher.doFinal(decodedBytes);
            return new String(decryptedBytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException("解密过程中出现错误", e);
        }
    }

    /**
     * 获取JWT的密钥
     *
     * @return 密钥
     */
    public SecretKey getSecretKeyJwt() {
        String jwtSecretKey = this.stringRedisTemplate.opsForValue().get(SECRET_KEY.addStringWithColon("jwt").transferToString());
        if (jwtSecretKey == null) {
            throw new NullPointerException("jwt secret key is null");
        }
        return Keys.hmacShaKeyFor(jwtSecretKey.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 获取AES的密钥
     *
     * @return 密钥
     */
    public SecretKey getSecretKeyAes() {
        String aesSecretKey = this.stringRedisTemplate.opsForValue().get(SECRET_KEY.addStringWithColon("aes").transferToString());
        if (aesSecretKey == null) {
            throw new NullPointerException("aes secret key is null");
        }
        return new SecretKeySpec(Base64.getDecoder().decode(aesSecretKey), "AES");
    }
}
